<?php

namespace app\admin\command;

use app\admin\model\Menu;
use app\admin\service\Auth;
use Illuminate\Console\Command;
use PragmaRX\Random\Random;
use support\Validator;
use Illuminate\Validation\Factory;

class Install extends Command
{
    const MENU_JSON_PATH = BASE_PATH . DIRECTORY_SEPARATOR . 'app' . DS . 'admin' . DS . 'command' . DS . 'installData' . DS . 'menu.json';

    protected $signature = 'admin:install';

    protected $description = '初始化admin数据';

    /**
     * @var Factory
     */
    protected $validate = null;

    public function handle()
    {
        if (!$this->confirm('安装将进行数据库迁移和菜单导入，是否继续?')) {
            $this->error("已取消安装!");
            return;
        }
        $this->info("正在执行数据库迁移...");
        $this->call('phinx:migrate');
        $this->validate = Validator::getInstance();
        $this->info("正在安装菜单...");
        $this->saveMenu($this->getMenuInit());
        $this->info("菜单安装完成");
        $this->info("生成api接口文档");
        $this->call(ApiDoc::class);
        $this->info("生成成功");
        $this->info("正在初始化管理员，请按照提示进行操作!");
        $this->createAdmin($this->getAdminData());
        $isMode = config('app.debug');
        $this->output->success("正在启动" . ($isMode ? "测试模式" : "正式模式") . "服务...");
        $this->call('worker', [
            'action' => 'start',
            'mode' => $isMode
        ]);
    }

    /**
     * 创建超级管理员
     * @param array $data
     */
    public function createAdmin($data)
    {
        $random = new Random();
        $row = new \app\admin\model\Admin();
        $row->nickname = "超级管理员";
        $row->username = $data['username'];
        $row->avatar = '/assets/admin/pear/admin/images/avatar.jpg';
        $row->salt = $random->alpha()->size(6)->get();
        $row->password = Auth::getEncryptPassword($data['password'], $row->salt);
        $row->loginfailure = 0;
        $row->logintime = date("Y-m-d H:i:s");
        $row->save();
    }

    /**
     * 获取输入信息
     * @return array
     */
    public function getAdminData()
    {
        res_username:
        $data['username'] = $this->ask('请输入初始化账号(eg.admin)');
        $validator = $this->validate->make($data, [
            'username' => 'required|min:2|max:12',
        ], [
            'required' => ':attribute必填',
            'min'      => ':attribute最小:min位',
            'max'      => ':attribute最大:max位',
        ], [
            'username' => '账号',
        ]);
        $boole = $this->alertError($validator);
        if (!$boole) {
            goto res_username;
        }
        res_password:
        $data['password'] = $this->secret('请输入初始化密码(eg.123456)');
        $data['password_confirmation'] = $this->secret('确认初始化密码');
        $validator = $this->validate->make($data, [
            'password' => 'required|min:6|max:64|confirmed',
        ], [
            'required'  => ':attribute必填',
            'min'       => ':attribute最小:min位',
            'max'       => ':attribute最大:max位',
            'confirmed' => ':attribute两次不正确',
        ], [
            'password' => '密码',
        ]);
        $boole = $this->alertError($validator);
        if (!$boole) {
            goto res_password;
        }
        return $data;
    }

    /**
     * 弹出错误信息
     * @param \Illuminate\Validation\Validator $validator
     */
    public function alertError(\Illuminate\Validation\Validator $validator)
    {
        $erros = $validator->errors();
        if (!$erros->isEmpty()) {
            $this->error("输入错误:");
            foreach ($erros->all() as $index => $msg) {
                $this->error($msg);
            }
            return false;
        }
        return true;
    }

    /**
     * 保存菜单
     * @param array $data
     * @param int $pid
     * @param string $pids
     */
    public function saveMenu($data, $pid = 0, $pids = '0')
    {
        if (empty($data)) {
            return;
        }
        foreach ($data as $value) {
            unset($value['id']);
            $child = $value['childlist'] ?? [];
            unset($value['childlist']);
            $value['pid'] = $pid;
            $value['pids'] = $pids;
            $row = new Menu();
            $row->fill($value);
            $row->save();
            // 递归增加子菜单
            if (!empty($child)) {
                $this->saveMenu($child, $row->id, $pids . ',' . $row->id);
            }
        }
    }

    /**
     * 获取初始化菜单数据
     * @return array
     */
    public function getMenuInit()
    {
        return json_decode(file_get_contents(self::MENU_JSON_PATH), true);
    }
}
